//! 分析文本
use crate::node::*;
use crate::runner::*;

use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;

/// 原始文件代码
#[derive(Debug)]
pub struct Code(Vec<String>);

impl From<Vec<String>> for Code {
    fn from(v: Vec<String>) -> Self {
        Self(v)
    }
}

impl From<Vec<&String>> for Code {
    fn from(v: Vec<&String>) -> Self {
        Self(v.into_iter().map(ToOwned::to_owned).collect())
    }
}

impl From<Vec<&str>> for Code {
    fn from(v: Vec<&str>) -> Self {
        Self(v.into_iter().map(ToOwned::to_owned).collect())
    }
}

impl Code {
    /// 从文件中获取每行代码 [去除空格]
    pub fn from_file<P: AsRef<std::path::Path>>(path: P) -> anyhow::Result<Self> {
        Ok(Code(
            BufReader::new(File::open(&path)?)
                .lines()
                .enumerate()
                .map(|(index, line)| match line {
                    Ok(line) => line.trim().to_string(),
                    Err(_) => {
                        crate::exit!(
                            "Unexpected trim error at line {}",
                            crate::color!(red => index + 1)
                        );
                        panic!();
                    }
                })
                .collect(),
        ))
    }

    pub fn to_nodes(&self) -> NodeList {
        let mut node_list: NodeList = self
            .0
            .iter()
            .enumerate()
            .map(|(i, code)| NodeType::classify(code, i))
            .collect::<Vec<Node>>()
            .into();

        node_list.init();
        node_list
    }
}
